package io.cici.cc.mybatis.plus.core.injector;


import io.cici.cc.mybatis.lite.mapping.MappedStatement;
import io.cici.cc.mybatis.lite.mapping.ResultMappings;
import io.cici.cc.mybatis.lite.mapping.SqlCommandType;
import io.cici.cc.mybatis.lite.mapping.SqlSource;
import io.cici.cc.mybatis.lite.session.Configuration;
import io.cici.cc.mybatis.lite.sql_source.scripting.LanguageDriver;
import io.cici.cc.mybatis.plus.core.assist.ISqlRunner;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Map;

/**
 * SqlRunner 注入器
 */
@Slf4j
@Setter
@Getter
public class SqlRunnerInjector {


    protected Configuration configuration;
    protected LanguageDriver languageDriver;

    public void inject(Configuration configuration) {
        this.configuration = configuration;

        this.initSelectList();
        this.initSelectObjs();
        this.initInsert();
        this.initUpdate();
        this.initDelete();
        this.initCount();
    }

    /**
     * 是否已经存在MappedStatement
     *
     * @param mappedStatement mappedStatement
     * @return 是否存在
     */
    private boolean hasMappedStatement(String mappedStatement) {
        return configuration.hasStatement(mappedStatement, false);
    }

    /**
     * 创建查询MappedStatement
     *
     * @param mappedStatement mappedStatement
     * @param sqlSource       执行的sqlSource
     * @param resultType      返回的结果类型
     */
    private void createSelectMappedStatement(String mappedStatement, SqlSource sqlSource, final Class<?> resultType) {
        MappedStatement mappedStatement1 = new MappedStatement.Builder(configuration, mappedStatement, sqlSource,
                SqlCommandType.SELECT).build();
        ResultMappings defaultResultMappings = new ResultMappings.Builder(configuration, "defaultResultMap", resultType,
                new ArrayList<>(0)).build();
        mappedStatement1.setResultMappings(defaultResultMappings);
        configuration.addMappedStatement(mappedStatement1);
    }

    /**
     * 创建一个MappedStatement
     *
     * @param mappedStatement mappedStatement
     * @param sqlSource       执行的sqlSource
     * @param sqlCommandType  执行的sqlCommandType
     */
    private void createUpdateMappedStatement(String mappedStatement, SqlSource sqlSource,
                                             SqlCommandType sqlCommandType) {
        MappedStatement mappedStatement1 = new MappedStatement.Builder(configuration, mappedStatement, sqlSource,
                sqlCommandType).build();
        ResultMappings defaultResultMappings = new ResultMappings.Builder(configuration, "defaultResultMap", int.class,
                new ArrayList<>(0)).build();
        mappedStatement1.setResultMappings(defaultResultMappings);
        configuration.addMappedStatement(mappedStatement1);
    }

    /**
     * initSelectList
     */
    private void initSelectList() {
        if (hasMappedStatement(ISqlRunner.SELECT_LIST)) {
            log.warn("MappedStatement 'SqlRunner.SelectList' Already Exists");
            return;
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
        createSelectMappedStatement(ISqlRunner.SELECT_LIST, sqlSource, Map.class);
    }

    /**
     * initSelectObjs
     */
    private void initSelectObjs() {
        if (hasMappedStatement(ISqlRunner.SELECT_OBJS)) {
            log.warn("MappedStatement 'SqlRunner.SelectObjs' Already Exists");
            return;
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Object.class);
        createSelectMappedStatement(ISqlRunner.SELECT_OBJS, sqlSource, Object.class);
    }

    /**
     * initCount
     */
    private void initCount() {
        if (hasMappedStatement(ISqlRunner.COUNT)) {
            log.warn("MappedStatement 'SqlRunner.Count' Already Exists");
            return;
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
        createSelectMappedStatement(ISqlRunner.COUNT, sqlSource, Long.class);
    }

    /**
     * initInsert
     */
    private void initInsert() {
        if (hasMappedStatement(ISqlRunner.INSERT)) {
            log.warn("MappedStatement 'SqlRunner.Insert' Already Exists");
            return;
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
        createUpdateMappedStatement(ISqlRunner.INSERT, sqlSource, SqlCommandType.INSERT);
    }

    /**
     * initUpdate
     */
    private void initUpdate() {
        if (hasMappedStatement(ISqlRunner.UPDATE)) {
            log.warn("MappedStatement 'SqlRunner.Update' Already Exists");
            return;
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
        createUpdateMappedStatement(ISqlRunner.UPDATE, sqlSource, SqlCommandType.UPDATE);
    }

    /**
     * initDelete
     */
    private void initDelete() {
        if (hasMappedStatement(ISqlRunner.DELETE)) {
            log.warn("MappedStatement 'SqlRunner.Delete' Already Exists");
            return;
        }
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, ISqlRunner.SQL_SCRIPT, Map.class);
        createUpdateMappedStatement(ISqlRunner.DELETE, sqlSource, SqlCommandType.DELETE);
    }
}
